akinao.namespace("akinao.ca");
(function() {

	function Map(x, y, loop) {
		var m = [];
		for (var i = x - 1;; i--) {
			m[i] = [];
			for (var j = y - 1;; j--) {
				m[i][j] = 0;
			}
		}
		this.loop = true == loop;
		this.sx = x;
		this.sy = y;
		this.map = m;
	}

	Map.prototype = {
		isOut : function(x, y) {
			return 0 > x || 0 > y || this.sx <= x || this.sy <= y;
		},
		get : function(x, y) {
			if (this.isOut(x, y)) {
				if (this.loop) {
					x = x % this.sx;
					y = y % this.sy;
				} else {
					return 0;
				}
			}
			return this.map[x][y];
		},
		set : function(x, y, v) {
			if (!this.isOut(x, y)) this.map[x][y] = v;
		}
	};

	function GenerationMap(x, y, rule) {
		this.sx = x;
		this.sy = y;
		this.map = [new Map(x, y), new Map(x, y)];
		this.now = 0;
		this.rule = rule;
	}

	GenerationMap.prototype = {
		isOut : function(x, y) {
			return this.map[this.now].isOut();
		},
		get : function(x, y) {
			return this.map[this.now].get(x, y);
		},
		set : function(x, y, v) {
			this.map[this.now].set(x, y, v);
		},
		next : function(fnc) {
			var rule = fnc || this.rule;
			var n = this.map[this.now], r = this.map[1 - this.now];
			var sx = this.sx, sy = this.sy;
			for (var x = sx - 1;; x--) {
				for (var y = sy - 1;; y--) {
					r.set(x, y, rule(x, y, n));
				}
			}
			this.now = 1 - this.now;
		}
	};

	akinao.ca = {
		GenerationMap : GenerationMap
	};

})();